package com.ucode.hrm.handle;

import cn.hutool.core.util.NumberUtil;
import com.ucode.model.hrm.HrmEmployeeCostDetail;

import java.math.BigDecimal;
import java.math.RoundingMode;

/**
 * 员工费用计算器
 */
public class EmployeeCostCalculator {


    /**
     * 计算单个员工的全部费用
     */
    public static void calculate(HrmEmployeeCostDetail detail) {

        // 1. 计算社保各项金额
        calculateSocialInsurance(detail);
        
        // 2. 计算公积金金额
        calculateHousingFund(detail);

        //3、计算加班工资
        BigDecimal total = NumberUtil.add(detail.getBaseSalary(),detail.getPositionSalary(),detail.getRegionalDifference(),detail.getTrafficSubsidy(),detail.getCommunicationSubsidy(),detail.getProfessionalAllowance(),detail.getComprehensiveSubsidy(),detail.getSalaryReissue(),detail.getReimbursement(),detail.getCommission());
        BigDecimal overtimeSalary = NumberUtil.sub(detail.getTotalPayable(),total);
        detail.setOvertimeSalary(overtimeSalary);

        //4、计算实发工资
        BigDecimal netSalary = NumberUtil.sub(detail.getTotalPayable(),detail.getSocialSecurityDeduction(),detail.getHousingFundDeduction(),detail.getIndividualIncomeTax());
        detail.setNetSalary(netSalary);

        //5、计算小计 = 应发工资+公积金（单位）+ 社保（单位）
        detail.setSubtotal(NumberUtil.add(detail.getTotalPayable(),detail.getUnitSocialSubtotal(),detail.getUnitHousingFund()));

        //6、费用合计 = 小计+服务费+节日福利
        detail.setTotalCost(NumberUtil.add(detail.getSubtotal(),detail.getServiceFee(),detail.getHolidayBenefits()));

    }
    
    /**
     * 计算社保各项金额
     */
    private static void calculateSocialInsurance(HrmEmployeeCostDetail detail) {

        // 单位社保部分计算
        detail.setUnitPension(calculate(detail.getPensionBase(), detail.getPensionUnitRatio()));//养老
        detail.setUnitUnemployment(calculate(detail.getUnemploymentBase(), detail.getUnemploymentUnitRatio()));//失业
        detail.setUnitInjury(calculate(detail.getInjuryBase(), detail.getInjuryUnitRatio()));//工伤
        detail.setUnitMaternity(calculate(detail.getMaternityBase(), detail.getMaternityUnitRatio()));//生育
        detail.setUnitMedical(calculate(detail.getMedicalBase(), detail.getMedicalUnitRatio()));//医疗
        detail.setUnitSeriousMedical(calculate(detail.getUnitSeriousMedicalBase(), detail.getSeriousMedicalUnitRatio()));//大病医疗
        detail.setUnitDisabilityInsurance(calculate(detail.getUnitDisabilityInsuranceBase(), detail.getUnitDisabilityInsuranceRatio()));//残保金
        // 单位社保小计
        BigDecimal unitSocialSubtotal = NumberUtil.add(detail.getUnitPension(),detail.getUnitUnemployment(),detail.getUnitInjury(),detail.getUnitMaternity(),detail.getUnitMedical(),detail.getUnitSeriousMedical(),detail.getUnitDisabilityInsurance());
        detail.setUnitSocialSubtotal(unitSocialSubtotal);


        // 个人社保部分计算
        detail.setIndividualPension(calculate(detail.getPensionBase(), detail.getPensionIndividualRatio()));//养老
        detail.setIndividualUnemployment(calculate(detail.getUnemploymentBase(), detail.getUnemploymentIndividualRatio()));//失业
        detail.setIndividualMedical(calculate(detail.getMedicalBase(), detail.getMedicalIndividualRatio()));//医疗
        detail.setIndividualLargeMedical(calculate(detail.getUnitSeriousMedicalBase(), detail.getLargeMedicalIndividualRatio()));//大病医疗
        detail.setLongTermPassportInsurance(calculate(detail.getLongTermPassportInsuranceBase(), detail.getLongTermPassportInsuranceRatio()));//长期护照险

        // 个人社保小计
        BigDecimal individualSocialSubtotal = NumberUtil.add(detail.getIndividualPension(),detail.getIndividualUnemployment(),detail.getIndividualMedical(),detail.getIndividualLargeMedical(),detail.getLongTermPassportInsurance());
        detail.setIndividualSocialSubtotal(individualSocialSubtotal);

        // 社保合计（单位+个人）
        BigDecimal totalSocialSecurity = NumberUtil.add(detail.getUnitSocialSubtotal(),detail.getIndividualSocialSubtotal());
        detail.setTotalSocialSecurity(totalSocialSecurity);

        //社保扣除(个人)
        detail.setSocialSecurityDeduction(detail.getIndividualSocialSubtotal());

    }
    
    /**
     * 计算公积金金额
     */
    private static void calculateHousingFund(HrmEmployeeCostDetail detail) {
        BigDecimal fundBase = detail.getHousingFundBase();
        
        // 计算单位和个人的公积金金额
        detail.setUnitHousingFund(calculate(fundBase, detail.getUnitHousingFundRate()));
        detail.setIndividualHousingFund(calculate(fundBase, detail.getIndividualHousingFundRate()));

        // 公积金合计（单位+个人）
        BigDecimal totalHousingFund = NumberUtil.add(detail.getUnitHousingFund(),detail.getIndividualHousingFund());
        detail.setTotalHousingFund(totalHousingFund);

        //公积金扣除(个人)
        detail.setHousingFundDeduction(detail.getIndividualHousingFund());
    }
    
    /**
     * 计算综合补贴
     */
    private static void calculateComprehensiveSubsidy(HrmEmployeeCostDetail detail) {
        // 1. 计算社保+公积金的总扣除额（单位+个人）
        BigDecimal deductionTotal = detail.getUnitSocialSubtotal()
                .add(detail.getIndividualSocialSubtotal())
                .add(detail.getUnitHousingFund())
                .add(detail.getIndividualHousingFund());
        
        // 2. 计算固定补贴（含服务费和节假日福利）
        BigDecimal fixedSubsidies = detail.getTotalPayable()
                .add(detail.getServiceFee())
                .add(detail.getHolidayBenefits());
        
        // 3. 总成本 -（社保公积金总扣除额 + 固定补贴）
        BigDecimal comprehensiveSubsidy = detail.getTotalCost()
                .subtract(deductionTotal)
                .subtract(fixedSubsidies);
        
        // 处理负值情况（计算结果不能为负）
        if (comprehensiveSubsidy.compareTo(BigDecimal.ZERO) < 0) {
            throw new IllegalStateException("计算结果为负: 综合补贴=" + comprehensiveSubsidy);
        }
        
        detail.setComprehensiveSubsidy(comprehensiveSubsidy);
    }
    
    /**
     * 基础计算：金额 × 百分比
     */
    private static BigDecimal calculate(BigDecimal amount, BigDecimal ratio) {
        return amount.multiply(NumberUtil.div(ratio,100))
                .setScale(2, RoundingMode.HALF_UP);
    }
}

